package uk.co.wobblycogs.vegas;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Map;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Graham Smith
 */
public final class PersistenceUtilities {

	private static final String PERSISTANCE_UNIT_NAME = "VegasPU";
	public static final String DRIVER_KEY = "javax.persistence.jdbc.driver";
	public static final String URL_KEY = "javax.persistence.jdbc.url";
	public static final String USER_KEY = "javax.persistence.jdbc.user";
	public static final String PASSWORD_KEY = "javax.persistence.jdbc.password";
	private static volatile PersistenceUtilities instance;
	private static final Logger logger = LoggerFactory.getLogger(PersistenceUtilities.class);
	private EntityManagerFactory emf;

	private PersistenceUtilities() {
	}

	public static PersistenceUtilities getInstance() {
		//double-checked lock - safe from Java 5 onwards.
		if (instance == null) {
			synchronized (PersistenceUtilities.class) {
				if (instance == null) {
					instance = new PersistenceUtilities();
				}
			}
		}
		return instance;
	}

	public EntityManagerFactory getEntityManagerFactory() {
		return emf;
	}

	/**
	 *
	 * @param emfSettings a map of settings passed directly to the factory
	 * creator.
	 * @return
	 */
	public EntityManagerFactory initializeEntityManagerFactory(Map<String, String> emfSettings) {
		if (emf == null) {
			synchronized (this) {
				if (emf == null) {
					logger.info("Creating new persistence unit");
					emf = Persistence.createEntityManagerFactory(PERSISTANCE_UNIT_NAME, emfSettings);
					logger.info("Persistence unit created");
				}
			}
		}
		return emf;
	}

	public void shutdown() {
		emf.close();
		emf = null;

		//TODO: What happens if we aren't using Derby?
		try {
			DriverManager.getConnection("jdbc:derby:;shutdown=true");
		} catch (SQLException sqle) {
			if ("XJ015".equals(sqle.getSQLState()) && 50000 == sqle.getErrorCode()) {
				logger.info("Derby shutdown");
			} else {
				logger.error("Failed to shutdown Derby.", sqle);
			}
		}
	}
}
